# This file is part of Email-Reminder.
#
# Email-Reminder is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# Email-Reminder is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Email-Reminder; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

package EmailReminder::Event;

# Base class for all other events.
#
# This class should never be used directly, use a derived class instead.

use strict;
use warnings;

use Date::Manip;
use XML::DOM;

use EmailReminder::Utils;

require Exporter;
our @ISA = ("Exporter");
our @EXPORT = qw(is_occurring get_recipients);

# XML tags, attributes and values

my $REMINDER_TAG = 'reminder';
my $REMINDERS_TAG = 'reminders';
my $RECIPIENT_TAG = 'recipient';
my $RECIPIENTS_TAG = 'recipients';

my $EMAIL_ATTR = 'email';
my $NAME_ATTR = 'name';
my $TYPE_ATTR = 'type';

my $DAYS_BEFORE_VAL = 'days before';
my $SAME_DAY_VAL = 'same day';

# Hard-coded value for this event's type (class method)
sub get_type
{
    return undef;
}

# Number of fields this event adds to its parent (class method)
sub get_nb_fields
{
    return 1;
}

sub new
{
    my $class = shift;
    my $event_node = shift;
    my $id = shift;

    my $this = { "OCCURRING" => 0,
                 "XML_NODE" => $event_node,
                 "ID" => $id,
                 "DATA" => [$id],
            };
    
    bless $this, $class;

    # Create empty data array
    my $count = $this->get_nb_fields() - 1;
    for (my $i = 0; $i < $count; $i++) {
        push(@{$this->{DATA}}, undef);
    }

    # Where to send this reminder email
    my $recipients = $this->{XML_NODE}->getElementsByTagName($RECIPIENTS_TAG)->item(0);
    if (defined($recipients)) {
        $this->{RECIPIENTS_NODE} = $recipients;
        $this->{RECIPIENTS_CACHE} = $this->get_recipients();
    }

    # Process reminders
    my $reminders = $this->{XML_NODE}->getElementsByTagName($REMINDERS_TAG)->item(0);
    if (defined($reminders)) {
        $this->{REMINDERS_NODE} = $reminders;
        $this->{REMINDERS_CACHE} = $this->get_reminders();
    }

    return $this;
}

sub unlink
{
    my $this = shift;
    my $node = $this->{XML_NODE};
    $node->getParentNode()->removeChild($node);
    $node->dispose();
}

sub get_recipients
{
    my $this = shift;

    if (!defined($this->{RECIPIENTS_CACHE})) {
        my @recipients = ();

        if (defined($this->{RECIPIENTS_NODE})) {
            foreach my $recipient ($this->{RECIPIENTS_NODE}->getElementsByTagName($RECIPIENT_TAG)) {
                my $email = $recipient->getAttribute($EMAIL_ATTR);
                if (defined($email)) {
                    my $name = $recipient->getAttribute($NAME_ATTR);
                    push(@recipients, [$email, $name]);
                }
            }
        }
        
        $this->{RECIPIENTS_CACHE} = \@recipients;
    }
    return $this->{RECIPIENTS_CACHE};
}

sub get_reminders
{
    my $this = shift;

    if (!defined($this->{REMINDERS_CACHE})) {
        my @reminders = ();

        if (defined($this->{REMINDERS_NODE}))
        {
            foreach my $reminder ($this->{REMINDERS_NODE}->getElementsByTagName($REMINDER_TAG)){
                my $type = $reminder->getAttribute($TYPE_ATTR);
                
                if ($type eq $SAME_DAY_VAL) {
                    push(@reminders, 0);
                    
                    if ($this->will_occur("")) {
                        $this->{WHEN} = "today";
                        $this->{OCCURRING}++;
                    }
                }
                elsif (($type eq $DAYS_BEFORE_VAL) && 
                       ($reminder->getFirstChild()))
                {
                    my $days = $reminder->getFirstChild()->getNodeValue();
                    push(@reminders, $days);
                    
                    if ($this->will_occur($days)) {
                        if ($days > 1) {
                            my $upcoming_date = DateCalc("today", "+${days}days");
                            $this->{WHEN} = "in $days days (" . UnixDate($upcoming_date, "%A %b %e") . ")";
                        }
                        elsif ($days == 1) {		
                            $this->{WHEN} = "tomorrow";
                        }		
                        elsif ($days == 0) {
                            $this->{WHEN} = "today";
                        }
                        else { 
                            next; # Negative days are ignored
                        } 
                        
                        $this->{OCCURRING}++;
                    }
                }
            }
        }

        $this->{REMINDERS_CACHE} = \@reminders;
    }

    return $this->{REMINDERS_CACHE};
}

sub set_reminders
{
    my ($this, $new_reminders) = @_;

    my $event = $this->{XML_NODE};
    my $doc = $event->getOwnerDocument();
    my $reminders = $this->{REMINDERS_NODE};

    if (!defined($reminders)) {
        # Create a blank <reminders> tag
        $reminders = $doc->createElement($REMINDERS_TAG);
        $event->appendChild($reminders);

        $this->{REMINDERS_NODE} = $reminders;
    }
    else {
        # TODO: preserve extra reminders in the XML but not in the UI

        # Delete all current reminders
        foreach my $child ($reminders->getChildNodes()) {
            $reminders->removeChild($child);
        }
    }
    
    # Add all reminders to the <reminders> node
    foreach my $nb_days (@$new_reminders)
    {
        my $new_node = $doc->createElement($REMINDER_TAG);
        
        if ($nb_days == 0)
        {
            $new_node->setAttribute($TYPE_ATTR, $SAME_DAY_VAL);
        }
        elsif ($nb_days > 0)
        {
            $new_node->setAttribute($TYPE_ATTR, $DAYS_BEFORE_VAL);
            $new_node->addText($nb_days);
        }
        else
        {
            # Invalid number, ignore
                next;
            }
        
        $reminders->appendChild($new_node);
    }

    # Clear the cache
    undef $this->{REMINDERS_CACHE};
}

sub is_occurring
{
    my $this = shift;
    return $this->{OCCURRING};
}

sub get_message
{
    my $this = shift;
    my $body = $this->get_message_body(@_);

    my $message = "";
    $message = <<MESSAGEEND if $body;
$body
Have a good day!

--
Sent by Email-Reminder $EmailReminder::Utils::VERSION
http://www.email-reminder.org.nz/
MESSAGEEND

    return $message;
}

sub data
{
    my $this = shift;
    return $this->{DATA};
}

sub get_id
{
    my $this = shift;
    return $this->{ID};
}

1;
